package com.linkoog.devtools.dubbo.toolwindow.workbenche.right;

import com.intellij.json.JsonLanguage;
import com.intellij.lang.Language;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.linkoog.devtools.utils.JacksonUtil;
import com.linkoog.devtools.utils.StringUtils;

import javax.swing.*;
import java.awt.*;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

public class ParamWidget implements Disposable {
    private Project project;
    public JPanel container;

    private FileEditor jsonBodyEditor;

    public ParamWidget(Project project){
        this.project = project;
        initPanel();
    }

    private void initPanel(){
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("paramType", Collections.EMPTY_LIST);
        map.put("param", Collections.EMPTY_LIST);

        jsonBodyEditor = createEditor(JsonLanguage.INSTANCE.getID(), JacksonUtil.toPrettyJson(map));
        container.add(jsonBodyEditor.getComponent(), BorderLayout.CENTER);
        Disposer.register(this, jsonBodyEditor);
    }

    public void setParamBody(Object param){
        if (param != null){
            setEditorDoc(jsonBodyEditor, JacksonUtil.toPrettyJson(param) );
        }else {
            setEditorDoc(jsonBodyEditor, "{\n}");
        }
    }

    public String getParamBody(){
        return getStringFromEditor(jsonBodyEditor);
    }


    /**
     * create editor with specified language and content
     */
    private FileEditor createEditor(String languageId, String text) {
        if (StringUtils.isEmpty(text)) {
            text = "";
        }

        Language language = Language.findLanguageByID(languageId);
        PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText(language, text);
        FileEditor editor = TextEditorProvider.getInstance().createEditor(project, psiFile.getVirtualFile());
        return editor;
    }

    /**
     * set content for editor
     */
    private void setEditorDoc(FileEditor editor, String text) {
        if (editor == null){
            return;
        }

        WriteCommandAction.runWriteCommandAction(project, (Computable<Boolean>) () -> {
            Document doc = getDocumentFromEditor(editor);
            doc.deleteString(0, doc.getTextLength());
            doc.setText(text == null ? "" : text.replaceAll("\\r", ""));
            return true;
        });
    }

    /**
     * get content from editor
     */
    private String getStringFromEditor(FileEditor editor) {
        Document doc = getDocumentFromEditor(editor);
        return doc.getText();
    }

    /**
     * get document from editor
     */
    private Document getDocumentFromEditor(FileEditor editor) {
        return FileDocumentManager.getInstance().getCachedDocument(editor.getFile());
    }

    @Override
    public void dispose() {

    }
}
